﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Constructor
{
    public partial class ConstructorForm : Form
    {
        public ConstructorForm()
        {
            InitializeComponent();
            Init(true);
            External.constructor = this.frameConstructor1;
            External.images = this.images1;
            External.images.LoadedImages = new Dictionary<string, PictureBox>();
            External.exemplars = this.exemplarConstructor1;
            frameConstructor1.AddField();
            last_ds = SaveInDataSet();
            frameConstructor1.Zoomed += new EventHandler<FrameConstructor.EventArgsZoom>(frameConstructor1_Zoomed);
            RefreshLastOpened();
            btn_ako.Checked = Properties.Settings.Default.showAKO;
            btn_sub.Checked = Properties.Settings.Default.showSubFrame;
            toolStripComboBox1.SelectedIndex = 4;
        }



        private DataSet all_data;
        private DataViewManager all_data_vm;
        public void Init(bool isInitDS)
        {
            if (isInitDS)
            {
                all_data = new DataSet("es_data");
                External.ds = all_data;
                all_data.Tables.Add("domens");
                all_data.Tables["domens"].Columns.Add("Название_домена");
                all_data.Tables["domens"].Columns.Add("type");
                all_data.Tables.Add("domens_params");
                all_data.Tables["domens_params"].Columns.Add("Название_домена");
                all_data.Tables["domens_params"].Columns.Add("Значения домена");
            }
            DataColumn dmn_key = all_data.Tables["domens"].Columns["Название_домена"];
            DataColumn dmnprm_key = all_data.Tables["domens_params"].Columns["Название_домена"];
            all_data.Tables["domens"].PrimaryKey = new DataColumn[] { all_data.Tables["domens"].Columns["Название_домена"] };
            DataRelation dmn_dmnprm = new DataRelation("domens_and_dparams", dmn_key, dmnprm_key);
            all_data.Relations.Add(dmn_dmnprm);
            all_data.Tables["domens_params"].PrimaryKey = new DataColumn[] { all_data.Tables["domens_params"].Columns["Название_домена"], 
                                                                                all_data.Tables["domens_params"].Columns["Значения домена"] };
            all_data_vm = all_data.DefaultViewManager;
            //******************domens           
            domens.DataSource = all_data_vm;
            domens.DataMember = "domens";
            domens.Columns[1].Visible = false;
            domens.Columns[0].HeaderText = "Название домена";
            domens.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            //******************domens_params            
            domens_params.DataSource = all_data_vm;
            domens_params.DataMember = "domens.domens_and_dparams";
            domens_params.Columns["Название_домена"].Visible = false;
            domens_params.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(domens_params_DataBindingComplete);
        }

        void domens_params_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            try
            {
                domens_params.Columns[0].Visible = false;
                domens_params.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            }
            catch
            {
            }
        }

        private void btn_add_dom_Click(object sender, EventArgs e)
        {
            int n = 1;
            while (all_data.Tables["domens"].Rows.Contains("NewDmn" + n.ToString()))
                n++;
            all_data.Tables["domens"].Rows.Add("NewDmn" + n.ToString());
            all_data.Tables["domens_params"].Rows.Add(new object[] { "NewDmn" + n.ToString(), "Да" });
            all_data.Tables["domens_params"].Rows.Add(new object[] { "NewDmn" + n.ToString(), "Нет" });
            domens.CurrentCell = domens.Rows[domens.Rows.Count - 1].Cells["Название_домена"];
            domens.BeginEdit(true);
        }

        private void btn_delete_dom_Click(object sender, EventArgs e)
        {
            if (domens.CurrentRow != null)
            {
                foreach (Frame frame in External.frames)
                    if (frame.isUsedDomain(domens.CurrentRow.Cells["Название_домена"].Value.ToString()))
                    {
                        MessageBox.Show("Этот домен используется во фрейме \"" + frame.Name + "\"");
                        return;
                    }
                if (MessageBox.Show("Вы действительно хотите удалить домен '" + domens.CurrentRow.Cells["Название_домена"].Value.ToString() + "'? ",
                                    "Удаление домена", MessageBoxButtons.YesNoCancel) == DialogResult.Yes)
                    domens.Rows.Remove(domens.CurrentRow);
            }
        }

        private void btn_add_value_Click(object sender, EventArgs e)
        {
            if (domens.CurrentRow != null)
            {
                if (domens.CurrentRow.Cells["Название_домена"].Value.ToString() == "Координаты")
                {
                    MessageBox.Show("Нельзя добавлять значения в этот домен");
                    return;
                }
                int n = 1;
                string dmn = domens.CurrentRow.Cells["Название_домена"].Value.ToString();
                while (all_data.Tables["domens_params"].Rows.Contains(new object[] { dmn, "NewVal" + n.ToString() }))
                    n++;
                all_data.Tables["domens_params"].Rows.Add(new object[] { dmn, "NewVal" + n.ToString() });
                domens_params.CurrentCell = domens_params.Rows[domens_params.Rows.Count - 1].Cells["Значения домена"];
                domens_params.BeginEdit(true);
            }
            else
                MessageBox.Show("Выделите домен!");
        }

        private void btn_delete_value_Click(object sender, EventArgs e)
        {
            if (domens_params.CurrentRow != null)
            {
                if (External.ds.Tables["domens_params"].Select("Название_домена ='" + domens.CurrentRow.Cells["Название_домена"].Value.ToString() + "'").Count() == 1)
                {
                    MessageBox.Show("Домен не может иметь меньше одного значения");
                }
                else
                    domens_params.Rows.Remove(domens_params.CurrentRow);
            }
        }
        private DataSet CreateDataSetStructure()
        {
            DataSet ds = new DataSet();
            ds.Tables.Add(External.ds.Tables["domens"].Copy());
            ds.Tables.Add(External.ds.Tables["domens_params"].Copy());
            DataTable dt = ds.Tables.Add("Frames");
            dt.Columns.Add("id");
            dt.Columns.Add("name");
            dt.Columns.Add("type");
            dt.Columns.Add("prototype");
            dt.Columns.Add("priority");
            DataTable dtslot = ds.Tables.Add("Slots");

            dtslot.Columns.Add("id");
            dtslot.Columns.Add("name");
            dtslot.Columns.Add("id_frame");
            dtslot.Columns.Add("id_domain");
            dtslot.Columns.Add("default");
            dtslot.Columns.Add("inherit");
            dtslot.Columns.Add("type");
            dtslot.Columns.Add("subframe");
            dtslot.Columns.Add("canbenull");
            DataTable dtProduction = ds.Tables.Add("Productions");

            dtProduction.Columns.Add("id");
            dtProduction.Columns.Add("owner_slot");
            dtProduction.Columns.Add("owner_frame");
            dtProduction.Columns.Add("slot");
            dtProduction.Columns.Add("operation");
            dtProduction.Columns.Add("type");
            dtProduction.Columns.Add("value");
            dtProduction.Columns.Add("marker");
            dtProduction.Columns.Add("procedure");

            DataTable dtProcedure = ds.Tables.Add("Procedures");
            dtProcedure.Columns.Add("id");
            dtProcedure.Columns.Add("owner_slot");
            dtProcedure.Columns.Add("owner_frame");
            dtProcedure.Columns.Add("method");

            DataTable dtParams = ds.Tables.Add("Params");
            dtParams.Columns.Add("id");
            dtParams.Columns.Add("owner_slot");
            dtParams.Columns.Add("owner_frame");
            dtParams.Columns.Add("name");
            dtParams.Columns.Add("value");

            DataTable dtImages = ds.Tables.Add("images");
            dtImages.Columns.Add("name");

            return ds;
        }

        private void InitTypeColumn(DataSet ds)
        {
            DataRow[] rows = ds.Tables["domens"].Select();
            for (int i = 0; i < rows.Count(); i++)
                rows[i]["type"] = new Domain(rows[i]["Название_домена"].ToString()).Type.ToString();
        }
        public bool SaveInFile()
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "Xml File|*.xml";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                SaveInFile(dlg.FileName);
                return true;
            }
            return false;
        }
        public void SaveInFile(string path)
        {
            DataSet ds = SaveInDataSet();
            ds.WriteXml(path);
            last_ds = SaveInDataSet();
            DSpath = path;
            SharedFuncs.AddLastOpened(path);
            RefreshLastOpened();
        }
        public DataSet SaveInDataSet()
        {
            DataSet ds = CreateDataSetStructure();
            InitTypeColumn(ds);
            ds.Tables.Add(frameConstructor1.SaveNodes());
            foreach (Frame f in External.frames)
                f.SaveInDataSet(ds);
            foreach (Frame f in MLO.MLOSource.Exemplars)
                f.SaveInDataSet(ds);
            images1.Save(ds);
            return ds;
        }

        public void LoadData()
        {
            if (DoSave())
            {
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Filter = "Xml File|*.xml";
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    SharedFuncs.AddLastOpened(dlg.FileName);
                    RefreshLastOpened();
                    EndLoadData(dlg.FileName);
                }
            }
        }

        public void LoadData(string path)
        {
            if (DoSave() && File.Exists(path) && path.EndsWith(".xml"))
            {
                EndLoadData(path);
                SharedFuncs.AddLastOpened(path);
            }
            else
                SharedFuncs.RemoveLastOpened(path);
            RefreshLastOpened();
        }
        private void EndLoadData(DataSet ds)
        {

            if (ds.Tables["domens"] != null)
            {
                all_data.Clear();
                all_data = new DataSet();
                all_data.Tables.Add(ds.Tables["domens"].Copy());
                all_data.Tables.Add(ds.Tables["domens_params"].Copy());
                External.ds = all_data;
                Init(false);
            }
            images1.Load(ds);
            frameConstructor1.Load(ds);
            last_ds = SaveInDataSet();
            exemplarConstructor1.Init();
        }

        private void EndLoadData(string path)
        {
            DataSet ds = new DataSet();
            ds.ReadXml(path);
            EndLoadData(ds);
            DSpath = path;
        }

        private void exemplar_tp_Enter(object sender, EventArgs e)
        {
            exemplarConstructor1.Init();
        }

        string old_value_coord = "";
        private void domens_params_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (domens_params.CurrentRow.Cells["Название_домена"].Value.ToString() == "Координаты")
                if (new Domain(domens_params.CurrentRow.Cells["Название_домена"].Value.ToString()).Type != CommonLib.DomainType.Number)
                {
                    MessageBox.Show("Значение для домена координат должно быть числовым");
                    domens_params.CurrentRow.Cells["Значения домена"].Value = old_value_coord;
                }
        }

        private void domens_params_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (domens_params.CurrentRow.Cells["Название_домена"].Value.ToString() == "Координаты")
                old_value_coord = domens_params.CurrentRow.Cells["Значения домена"].Value.ToString();
        }

        #region Menu

        DataSet last_ds = null;
        string DSpath = string.Empty;

        private bool DoSave()
        {
            if (!SharedFuncs.DataSetEquals(SaveInDataSet(), last_ds))
            {
                DialogResult dr = MessageBox.Show("Сохранить базу перед выходом?", "", MessageBoxButtons.YesNoCancel);
                switch (dr)
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        if (DSpath == string.Empty)
                            return SaveInFile();
                        else
                            SaveInFile(DSpath);
                        break;
                    case System.Windows.Forms.DialogResult.Cancel:
                        return false;
                }
            }
            return true;
        }

        private void сохранитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (DSpath == string.Empty)
                SaveInFile();
            else
                SaveInFile(DSpath);
        }

        private void загрузитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadData();
        }

        private void сохранитьКакToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveInFile();
        }

        private void выходToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ConstructorForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!DoSave())
                e.Cancel = true;
        }

        private void RefreshLastOpened()
        {
            последниеToolStripMenuItem.DropDownItems.Clear();
            foreach (string str in SharedFuncs.LastOpened)
            {
                ToolStripMenuItem tmi = new System.Windows.Forms.ToolStripMenuItem();
                tmi.Text = str;
                tmi.Click += new EventHandler(tmi_Click);
                this.последниеToolStripMenuItem.DropDownItems.Add(tmi);
            }
        }

        void tmi_Click(object sender, EventArgs e)
        {
            LoadData((sender as ToolStripMenuItem).Text);
        }

        private void настройкиToolStripMenuItem_Click(object sender, EventArgs e)
        {
            (new SettingsForm()).ShowDialog();
        }
        #endregion

        //private void стартToolStripMenuItem1_Click(object sender, EventArgs e)
        //{
        //    backupDS = SaveInDataSet();
        //    MLO.MLO.Start();
        //    var exemp = MLO.MLOSource.exemplars.ToList();
        //    EndLoadData(backupDS);
        //    MLO.MLOSource.exemplars = exemp;
        //    exemplarConstructor1.Init();
        //}

        #region Zoom
        private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            float temp;
            if (float.TryParse((sender as ToolStripComboBox).Text.TrimEnd('%'), out temp))
            {
                frameConstructor1.Zoom(temp);
                toolStripComboBox1.Text = temp.ToString() + "%";
            }
            else
            {
                frameConstructor1.Zoom(-1);
                toolStripComboBox1.Text = "Вся область";
            }
        }
        void frameConstructor1_Zoomed(object sender, FrameConstructor.EventArgsZoom e)
        {
            toolStripComboBox1.Text = e.Zoom.ToString() + "%";
        }
        private void toolStripComboBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                toolStripComboBox1_SelectedIndexChanged(toolStripComboBox1, null);
        }
        #endregion

        private void btn_ako_CheckedChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.showAKO = btn_ako.Checked;
            Properties.Settings.Default.Save();
            frameConstructor1.DrawLinks();
        }

        private void btn_sub_CheckedChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.showSubFrame = btn_sub.Checked;
            Properties.Settings.Default.Save();
            frameConstructor1.DrawLinks();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(FunctionControler.ListMethods()[0]);
            //FunctionControler.Caller("EndGame",External.SearchFrame("Поле"));
        }

        private void поверхВсехОконToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            this.TopMost = поверхВсехОконToolStripMenuItem.Checked;
        }

        private void справкаToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start(Path.Combine(Application.StartupPath, "TribeBattle.chm"));
        }
        DataSet backupDS = null;
        private void стартToolStripMenuItem2_Click(object sender, EventArgs e)
        {
            backupDS = SaveInDataSet();
            MLO.MLO.Start(true);
            var tempParents = External.Parents.ToDictionary(o => o.Key, o => o.Value);
            var exemp = MLO.MLOSource.Exemplars.ToList();
            EndLoadData(backupDS);
            MLO.MLOSource.Exemplars.Clear();
            MLO.MLOSource.Exemplars.AddRange(exemp);
            External.Parents = tempParents;
            exemplarConstructor1.Init();
            External.exemplars.exemplarProperties.Hide();
        }

        private void откатитьБазуToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (backupDS != null)
            {
                EndLoadData(backupDS);
            }
        }

        private void ConstructorForm_Load(object sender, EventArgs e)
        {

        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void toolStripButton_Next_step_Click(object sender, EventArgs e)
        {
            backupDS = SaveInDataSet();
            MLO.MLO.Start(false);
            var tempParents = External.Parents.ToDictionary(o => o.Key, o => o.Value);
            var exemp = MLO.MLOSource.Exemplars.ToList();
            EndLoadData(backupDS);
            MLO.MLOSource.Exemplars.Clear();
            MLO.MLOSource.Exemplars.AddRange(exemp);
            External.Parents = tempParents;
            exemplarConstructor1.Init();
            External.exemplars.exemplarProperties.Hide();
        }


    }
}
